package com.mingqijia.gassafety.console.controller.client;

import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gap.basic.base.CommonResponse;
import com.gap.cache.redis.RedisCache;
import com.github.pagehelper.util.StringUtil;
import com.mingqijia.gassafety.authority.api.resp.config.DictionaryItemRespDTO;
import com.mingqijia.gassafety.authority.dal.helper.ConfigureHolder;
import com.mingqijia.gassafety.db.entity.*;
import com.mingqijia.gassafety.db.entity.redis.LatestLog;
import com.mingqijia.gassafety.db.mapper.DeviceStateMapper;
import com.mingqijia.gassafety.db.mapper.FieldTemplateMapper;
import com.mingqijia.gassafety.shared.constant.*;
import com.mingqijia.gassafety.shared.utils.commonUtils.PageUtil;
import com.mingqijia.gassafety.webserver.feign.ConsoleSkFeignClient;
import com.mingqijia.gassafety.webserver.request.RecordLogRequest;
import com.mingqijia.gassafety.webserver.request.client.ClientDtuListRequest;
import com.mingqijia.gassafety.webserver.response.AlertLogResponse;
import com.mingqijia.gassafety.webserver.response.BrokenLogResponse;
import com.mingqijia.gassafety.webserver.response.client.ClientAlertRes;
import com.mingqijia.gassafety.webserver.response.client.ClientEquipmentDetailRes;
import com.mingqijia.gassafety.webserver.response.client.ConcentrationCurveRes;
import com.mingqijia.gassafety.webserver.response.client.DtuResponse;
import com.mingqijia.gassafety.webserver.response.sk.AlarmSupplierListVo;
import com.mingqijia.gassafety.webserver.response.sk.ConsoleSkSupplierListResponse;
import com.mingqijia.gassafety.webserver.service.*;
import com.mingqijia.gassafety.webserver.service.cmp.EquipmentCmpService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 实时状态
 *
 * @author guoliang.lao
 * @since 2022-02-18
 */

@Slf4j
@Api(tags = "C端-设备信息")
@RestController(value = "EquipmentController")
@RequestMapping({"/h5/business/v1/equipment", "/console/v1/openapi"})
public class EquipmentController {

    @Autowired
    RedisCache redisCache;
    @Autowired
    EquipmentService equipmentService;
    @Autowired
    LatestLogService latestLogService;
    @Autowired
    ConsumerService consumerService;
    @Autowired
    ContactsService contactsService;
    @Autowired
    ConfigureHolder holder;
    @Autowired
    HistoryAlarmService historyAlarmService;
    @Autowired
    HistoryBrokenService historyBrokenService;
    @Autowired
    HistoryLogService historyLogService;
    @Autowired
    CustomerSubsHistoryService subsHistoryService;
    @Autowired
    private CompanyService companyService;
    @Autowired
    FieldTemplateMapper fieldTemplateMapper;
    @Autowired
    ReceiverValveService receiverValveService;
    @Autowired
    DeviceStateMapper deviceStateMapper;

    @Autowired
    EquipmentCmpService equipmentCmpService;


    @ApiOperation("设备详情")
    @RequestMapping(value = {"detail","alarm/detail"}, method = RequestMethod.GET)
    public CommonResponse<ClientEquipmentDetailRes> detail(@RequestParam @ApiParam(value = "设备号") String imei){
        ClientEquipmentDetailRes res = new ClientEquipmentDetailRes();
        //设备基础信息
        LambdaQueryWrapper<Dtu> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(Dtu::getIMEI,imei).eq(Dtu::getIsDeleted,0);
        Dtu equipment = equipmentService.getOne(queryWrapper);
        if (equipment == null) {
            return CommonResponse.failure("设备不存在");
        }
        BeanUtils.copyProperties(equipment,res);
        res.setImei(equipment.getIMEI());
        res.setEquipmentName(equipment.getName());
        //设备类型
        if (!StringUtils.isEmpty(res.getEquipmentType())) {
            DictionaryItemRespDTO equipmentTypeDict = holder.getDictionaryByKey(
                    EquipmentType.DICT_CODE).stream().filter(a->a.getValue().equals(
                    res.getEquipmentType())).collect(Collectors.toList()).get(0);
            res.setEquipmentTypeName(equipmentTypeDict.getName());
        }
        //设备厂商
        if (!StringUtils.isEmpty(res.getEquipmentManufacturer())) {
            //设备厂商名称
            ConsoleSkSupplierListResponse response = equipmentCmpService.supplierListRequest();
            log.info("调用厨房查询厂商接口返回：{}", response);
            if (response != null && response.getCode() == 0 && response.getData() != null && org.apache.commons.collections.CollectionUtils.isNotEmpty(response.getData())) {
                res.setEquipmentManufacturer(response.getData().stream().filter(a->a.getAlarmSystemCode().equals(
                        equipment.getEquipmentManufacturer())).collect(Collectors.toList()).get(0).getMsName());
            }

        }
        //检测类型
        if (!StringUtils.isEmpty(res.getDetectionType())) {
            String detectionType = "";
            String[] detectionTypes = equipment.getDetectionType().split(";");
            for (String s : detectionTypes) {
                DictionaryItemRespDTO detectionTypeDict = holder.getDictionaryByKey(
                        Constants.DETECTION_TYPE_CODE).stream().filter(a->a.getValue().equals(
                        s)).collect(Collectors.toList()).get(0);
                detectionType = detectionType + detectionTypeDict.getName() + ";";
            }
            res.setDetectionType(detectionType);
        }
        //redis实时信息
        LatestLog latestLog = latestLogService.get(equipment.getIMEI(),equipment.getSpId());
        if (latestLog != null) {
            BeanUtils.copyProperties(latestLog,res);
        }
        //信号值
        if (res.getEquipmentStatus().equals(EquipmentStatus.offline)) {
            res.setSignal(SignalEnum.LEVEL_0.getLevel());
            res.setSignalStr(SignalEnum.LEVEL_0.getName());
        } else {
            res.setSignal(latestLog.getSignal());
            res.setSignalStr(latestLog.getSignalStr());
        }
        //查询控制器的点位数
        if (equipment.getEquipmentType().equals(EquipmentType.GAS_ALARM_CONTROLLER.getCode())) {
            LambdaQueryWrapper<Dtu> pointWrapper = new LambdaQueryWrapper();
            pointWrapper.likeRight(Dtu::getIMEI,imei+"-").eq(Dtu::getIsDeleted,0);
            List<Dtu> pointList = equipmentService.list(pointWrapper);
            //去除控制器，剩余点位数
            res.setPoint(pointList.size());
        }
        if (res.getValidity() == null) res.setValidity(0);
        if (res.getExpirationTime() == null) res.setExpirationTime("");
        if (res.getEquipmentModel() == null) res.setEquipmentModel("");
        LambdaQueryWrapper<ReceiverValve> queryWrapper1 = new LambdaQueryWrapper();
        queryWrapper1.eq(ReceiverValve::getDeviceId,equipment.getId()).eq(ReceiverValve::getIsDeleted, Constants.IS_DELETED_FALSE)
                .eq(ReceiverValve::getSpId, equipment.getSpId());
        ReceiverValve receiverValve = receiverValveService.getOne(queryWrapper1);
        log.info("alarm/detail receiverValve:", receiverValve);
        if (receiverValve != null) {
            BeanUtils.copyProperties(receiverValve,res);
        }
        //查询设备所属客户的户号
        if (equipment.getConsumerId() != null && equipment.getConsumerId() > 0) {
            Consumer consumer = consumerService.getById(equipment.getConsumerId());
            if (consumer != null) res.setSubsCode(consumer.getSubsCode());
        }
        return CommonResponse.success(res);
    }


    @ApiOperation("多个设备详情")
    @RequestMapping(value = "alarm/{deviceId}", method = RequestMethod.GET)
    public CommonResponse<List<ClientEquipmentDetailRes>> multiDetails(
            @PathVariable @ApiParam(value = "设备号") String[] deviceId) {
        if (null == deviceId) {
            return CommonResponse.failure("设备Id不能为空");
        }
        List<String> deviceIds = Arrays.stream(deviceId).collect(Collectors.toList());

        //设备基础信息
        LambdaQueryWrapper<Dtu> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.in(Dtu::getIMEI, deviceIds).eq(Dtu::getIsDeleted,0);
        List<Dtu> equipments = equipmentService.list(queryWrapper);
        if (CollectionUtils.isEmpty(equipments)) {
            return CommonResponse.failure("设备不存在");
        }
        //设备厂商名称
        ConsoleSkSupplierListResponse response = equipmentCmpService.supplierListRequest();
        log.info("调用厨房查询厂商接口返回：{}", response);
        List<AlarmSupplierListVo> supplierListVos = new ArrayList<>();
        if (response != null && response.getCode() == 0 && response.getData() != null && org.apache.commons.collections.CollectionUtils.isNotEmpty(response.getData())) {
            supplierListVos = response.getData();
        }
        List<ClientEquipmentDetailRes> results = new ArrayList<>();
        List<AlarmSupplierListVo> finalSupplierListVos = supplierListVos;
        equipments.forEach(equipment -> {
            ClientEquipmentDetailRes res = new ClientEquipmentDetailRes();
            BeanUtils.copyProperties(equipment,res);
            res.setImei(equipment.getIMEI());
            res.setEquipmentName(equipment.getName());

            //设备类型
            if (!StringUtils.isEmpty(res.getEquipmentType())) {
                DictionaryItemRespDTO equipmentTypeDict = holder.getDictionaryByKey(
                        EquipmentType.DICT_CODE).stream().filter(a->a.getValue().equals(
                        res.getEquipmentType())).collect(Collectors.toList()).get(0);
                res.setEquipmentTypeName(equipmentTypeDict.getName());
            }
            //设备厂商
            if (!StringUtils.isEmpty(res.getEquipmentManufacturer())) {
                res.setEquipmentManufacturer(finalSupplierListVos.stream().filter(a->a.getAlarmSystemCode().equals(
                        equipment.getEquipmentManufacturer())).collect(Collectors.toList()).get(0).getMsName());
            }
            //检测类型
            if (!StringUtils.isEmpty(res.getDetectionType())) {
                String detectionType = "";
                String[] detectionTypes = equipment.getDetectionType().split(";");
                for (String s : detectionTypes) {
                    DictionaryItemRespDTO detectionTypeDict = holder.getDictionaryByKey(
                            Constants.DETECTION_TYPE_CODE).stream().filter(a->a.getValue().equals(
                            s)).collect(Collectors.toList()).get(0);
                    detectionType = detectionType + detectionTypeDict.getName() + ";";
                }
                res.setDetectionType(detectionType);
            }
            //redis实时信息
            LatestLog latestLog = latestLogService.get(equipment.getIMEI(),equipment.getSpId());
            if (latestLog != null) {
                BeanUtils.copyProperties(latestLog,res);
            }
            //信号值
            if (res.getEquipmentStatus().equals(EquipmentStatus.offline)) {
                res.setSignal(SignalEnum.LEVEL_0.getLevel());
                res.setSignalStr(SignalEnum.LEVEL_0.getName());
            } else {
                res.setSignal(latestLog.getSignal());
                res.setSignalStr(latestLog.getSignalStr());
            }
            //查询控制器的点位数
            if (equipment.getEquipmentType().equals(EquipmentType.GAS_ALARM_CONTROLLER.getCode())) {
                LambdaQueryWrapper<Dtu> pointWrapper = new LambdaQueryWrapper();
                pointWrapper.likeRight(Dtu::getIMEI,equipment.getIMEI() +"-").eq(Dtu::getIsDeleted,0);
                List<Dtu> pointList = equipmentService.list(pointWrapper);
                //去除控制器，剩余点位数
                res.setPoint(pointList.size());
            }
            if (res.getValidity() == null) res.setValidity(0);
            if (res.getExpirationTime() == null) res.setExpirationTime("");
            if (res.getEquipmentModel() == null) res.setEquipmentModel("");
            LambdaQueryWrapper<ReceiverValve> queryWrapper1 = new LambdaQueryWrapper();
            queryWrapper1.eq(ReceiverValve::getDeviceId,equipment.getId()).eq(ReceiverValve::getIsDeleted,0)
                    .eq(ReceiverValve::getIsDeleted, Constants.IS_DELETED_FALSE)
                    .eq(ReceiverValve::getSpId, equipment.getSpId());
            ReceiverValve receiverValve = receiverValveService.getOne(queryWrapper1);
            if (receiverValve != null) {
                BeanUtils.copyProperties(receiverValve,res);
            }
            results.add(res);
        });
        return CommonResponse.success(results);
    }

    @ApiOperation("报警记录")
    @RequestMapping(value = {"alertList", "alarm/alert"}, method = RequestMethod.GET)
    public CommonResponse<PageUtil<ClientAlertRes>> alertBrokenList(@RequestParam @ApiParam(value = "设备号") String imei,
                                                                    @RequestParam @ApiParam(value = "页数") Integer page,
                                                                    @RequestParam @ApiParam(value = "条数") Integer pageSize){
        List<ClientAlertRes> resultList = new ArrayList<>();
        //设备基础信息
        LambdaQueryWrapper<Dtu> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(Dtu::getIMEI,imei).eq(Dtu::getIsDeleted,0);
        Dtu equipment = equipmentService.getOne(queryWrapper);
        if (equipment == null) {
            return CommonResponse.failure("设备不存在");
        }
        if (EquipmentType.GAS_ALARM_CONTROLLER.getCode().equals(equipment.getEquipmentType())) {
            return CommonResponse.success(new PageUtil(page, pageSize,0,new ArrayList()));
        }
        RecordLogRequest req = new RecordLogRequest();
        req.setImei(imei);
        req.setSpId(equipment.getSpId());
        req.setPage(page);
        req.setPageSize(pageSize);
        req.setTemplateType(TemplateTypeEnum.TEMPLATE_TYPE_1.getCode());
        PageUtil<AlertLogResponse> pageUtil = historyAlarmService.getAlarmList(req);
        for (AlertLogResponse alertLogResponse : pageUtil.getList()) {
            ClientAlertRes res = new ClientAlertRes();
            res.setImei(alertLogResponse.getImei());
            res.setEventTime(alertLogResponse.getLatestTime());
            res.setEquipmentManufacturer("报警");
            res.setEventInfo("");
            resultList.add(res);
        }
        PageUtil pageInfo = new PageUtil(req.getPage(), req.getPageSize(), pageUtil.getTotal(), resultList);
        return CommonResponse.success(pageInfo);
    }

    @ApiOperation("故障记录")
    @RequestMapping(value = {"brokenList", "alarm/broken"}, method = RequestMethod.GET)
    public CommonResponse<PageUtil<ClientAlertRes>> brokenList(@RequestParam @ApiParam(value = "设备号") String imei,
                                                               @RequestParam @ApiParam(value = "页数") Integer page,
                                                               @RequestParam @ApiParam(value = "条数") Integer pageSize){
        List<ClientAlertRes> resultList = new ArrayList<>();
        //设备基础信息
        LambdaQueryWrapper<Dtu> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(Dtu::getIMEI,imei).eq(Dtu::getIsDeleted,0);
        Dtu equipment = equipmentService.getOne(queryWrapper);
        if (equipment == null) {
            return CommonResponse.failure("设备不存在");
        }
        RecordLogRequest req = new RecordLogRequest();
        req.setImei(imei);
        req.setSpId(equipment.getSpId());
        req.setPage(page);
        req.setPageSize(pageSize);
        req.setTemplateType(TemplateTypeEnum.TEMPLATE_TYPE_1.getCode());
        PageUtil<BrokenLogResponse> pageUtil = historyBrokenService.getList(req);
        for (BrokenLogResponse brokenLogResponse : pageUtil.getList()) {
            ClientAlertRes res = new ClientAlertRes();
            res.setImei(brokenLogResponse.getImei());
            res.setEventTime(brokenLogResponse.getLatestTime());
            res.setEquipmentManufacturer("故障");
            res.setEventInfo(brokenLogResponse.getBrokenReason());
            resultList.add(res);
        }
        PageUtil pageInfo = new PageUtil(req.getPage(), req.getPageSize(), pageUtil.getTotal(), resultList);
        return CommonResponse.success(pageInfo);
    }

    @ApiOperation("报警浓度曲线")
    @RequestMapping(value = {"historyLog", "alarm/log"}, method = RequestMethod.GET)
    public CommonResponse<List<ConcentrationCurveRes>> historyLog(@RequestParam @ApiParam(value = "设备号") String imei,
                                                                  @RequestParam @ApiParam(value = "开始时间") String timeStart,
                                                                  @RequestParam @ApiParam(value = "结束时间") String timeEnd){
        if (StringUtils.isEmpty(imei)) return CommonResponse.failure("设备号不能为空！");
        if (StringUtils.isEmpty(timeStart)) return CommonResponse.failure("开始时间不能为空！");
        if (StringUtils.isEmpty(timeEnd)) return CommonResponse.failure("结束时间不能为空！");
        return CommonResponse.success(historyLogService.getConcentrationCurve(imei,timeStart,timeEnd));
    }


    @ApiOperation("报警器列表")
    @RequestMapping(value = "/equipmentList", method = RequestMethod.POST)
    public CommonResponse<List<DtuResponse>> equipmentList(@RequestBody @Valid ClientDtuListRequest request){
        
        subsHistoryService.checkH5Request(request.getOrgId(),request.getPhone(),request.getVccUserId());
        
        List<DtuResponse> dtuResponses = null;
//      String orgCode = companyService.getOrgCodeBySpId(request.getOrgCode());
        //将 orgCode换spId
        String spId = companyService.getSpId( request.getOrgCode() );
        log.info("equipmentList spId: {}", spId);
        //根据spId得到模板类型, 模板一传户号 或手机号
        FieldTemplate template = fieldTemplateMapper.getTypeBySpId(spId);
        if (template.getTemplateType().equals(Constants.BIND_CHANNEL_GAS)){
            //传入户号判断绑定情况
            if (  StringUtil.isNotEmpty(request.getSubsCode())) {
                subsHistoryService.isBindSus(request,spId);
            }
            dtuResponses = equipmentService.clientDtuListBySubs( request ,spId, template);
        }else if (template.getTemplateType().equals(Constants.BIND_CHANNEL_ASST)){
            dtuResponses = equipmentService.clientDtuListBySubs( request ,spId, template);
        }
        return CommonResponse.success( dtuResponses );

    }

    @ApiOperation("报警器列表(for kitchen) 弃用")
    @PostMapping(value = "/alarm/list")
    public CommonResponse<List<DtuResponse>> equipmentList4Get(@RequestBody @Valid ClientDtuListRequest request) {
        log.info("equipmentList4Get request: {}", request);
        CommonResponse<List<DtuResponse>> dtus = null;
        try {
            dtus = equipmentList( request );
        } catch (Exception e) {
            log.error("报警器列表失败，", e);
        }
        log.info("equipmentList4Get dtus: {}", dtus);
        if (ObjectUtils.isEmpty(dtus)) {
            return CommonResponse.success(Collections.emptyList());
        }
        String spId = companyService.getSpId( request.getOrgCode() );
        if (!CollectionUtils.isEmpty(dtus.getData())) {
            // 过滤家用并赋值信号
            dtus.getData().stream().filter(item -> StringUtils.hasText(item.getEquipmentType())
                    && item.getEquipmentType().contains("家用")).forEach(dtu -> {
                //redis实时信息
                LatestLog latestLog = latestLogService.get(dtu.getImei(), spId);
                if (ObjectUtils.isEmpty(latestLog)) {
                    return;
                }
                //信号值
                if (latestLog.getEquipmentStatus().equals(EquipmentStatus.offline)) {
                    dtu.setSignal(SignalEnum.LEVEL_0.getLevel());
                } else {
                    dtu.setSignal(latestLog.getSignal());
                }
            });
        }

        return dtus;
    }

//    @ApiOperation("报警器列表(for kitchen)")
//    @GetMapping(value = "/alarm/list/multi")
//    public CommonResponse<List<DtuResponse>> equipmentList4GetArray(@Valid String requests) {
//        CommonResponse<List<DtuResponse>> dtus = null;
//        List<ClientDtuListRequest> requestArray = JSONUtil.toList(JSONUtil.parseArray(requests), ClientDtuListRequest.class);
//        requestArray.forEach(request -> {
//            try {
//                String spId = companyService.getSpId( request.getOrgCode() );
//                //根据spId得到模板类型, 模板二必须传户号
//                FieldTemplate template = fieldTemplateMapper.getTypeBySpId(spId);
//                if (template.getTemplateType().equals(Constants.BIND_CHANNEL_GAS)){
//                    if (  StringUtil.isEmpty(request.getSubsCode())) return CommonResponse.failure("户号不能为空！");
//                    subsHistoryService.isBindSus(request,spId);
//                    dtuResponses = equipmentService.clientDtuListBySubsArray( requestArray ,spId, template);
//                }else if (template.getTemplateType().equals(Constants.BIND_CHANNEL_ASST)){
//                    dtuResponses = equipmentService.clientDtuListBySubsArray( requestArray ,spId, template);
//                }
//            } catch (Exception e) {
//                log.error("报警器列表失败，", e);
//            }
//        });
//
//        if (ObjectUtils.isEmpty(dtus)) {
//            return CommonResponse.success(Collections.emptyList());
//        }
//        String spId = companyService.getSpId( request.getOrgCode() );
//        if (!CollectionUtils.isEmpty(dtus.getData())) {
//            // 过滤家用并赋值信号
//            dtus.getData().stream().filter(item -> StringUtils.hasText(item.getEquipmentType())
//                    && item.getEquipmentType().contains("家用")).forEach(dtu -> {
//                //redis实时信息
//                LatestLog latestLog = latestLogService.get(dtu.getImei(), spId);
//                if (ObjectUtils.isEmpty(latestLog)) {
//                    return;
//                }
//                //信号值
//                if (latestLog.getEquipmentStatus().equals(EquipmentStatus.offline)) {
//                    dtu.setSignal(SignalEnum.LEVEL_0.getLevel());
//                } else {
//                    dtu.setSignal(latestLog.getSignal());
//                }
//            });
//        }
//
//        return dtus;
//    }
}

